package gti310.tp4;

public class DCT {
	static public double[][] transform(double[][] matrix) {
		// O(n^4)
		return dct(matrix);
	}

	static public double[][] deTransform(double[][] matrix) {
		// O(n^4)
		return idct(matrix);
	}

	static private double[][] idct(double[][] matrix) {
		double[][] idctMatrix = new double[Main.BLOCK_SIZE][Main.BLOCK_SIZE];
		for (int i = 0; i < Main.BLOCK_SIZE; i++) {
			for (int j = 0; j < Main.BLOCK_SIZE; j++) {
				double dctv = SumCosineIdct(i, j, matrix);
				idctMatrix[i][j] = dctv;
			}
		}
		return idctMatrix;
	}

	private static double SumCosineIdct(int i, int j, double[][] matrix) {
		double value = 0.0;
		for (double u = 0; u < Main.BLOCK_SIZE; u++) {
			for (double v = 0; v < Main.BLOCK_SIZE; v++) {
				value += ((2 * c(u) * c(v)) / (Math.sqrt(Main.BLOCK_SIZE
						* Main.BLOCK_SIZE)))
						* Math.cos(((2 * (double) i + 1) * u * Math.PI)
								/ (2 * Main.BLOCK_SIZE))
						* Math.cos(((2 * (double) j + 1) * v * Math.PI)
								/ (2 * Main.BLOCK_SIZE))
						* (matrix[(int) u][(int) v]);
			}
		}
		return value;
	}

	static private double[][] dct(double[][] matrix) {
		double[][] dctMatrix = new double[Main.BLOCK_SIZE][Main.BLOCK_SIZE];
		for (int u = 0; u < Main.BLOCK_SIZE; u++) {
			for (int v = 0; v < Main.BLOCK_SIZE; v++) {
				double dctv = (2 * c(u) * c(v) / Math.sqrt(Main.BLOCK_SIZE
						* Main.BLOCK_SIZE))
						* SumCosine(u, v, matrix);
				dctMatrix[u][v] = dctv;
			}
		}
		return dctMatrix;

	}

	static private double SumCosine(int u, int v, double[][] matrix) {
		double value = 0;
		for (int i = 0; i < Main.BLOCK_SIZE; i++) {
			for (int j = 0; j < Main.BLOCK_SIZE; j++) {
				value += Math.cos((2 * i + 1) * u * Math.PI
						/ (2 * Main.BLOCK_SIZE))
						* Math.cos((2 * j + 1) * v * Math.PI
								/ (2 * Main.BLOCK_SIZE)) * (matrix[i][j]);
			}
		}

		return value;

	}

	static private double c(double w) {
		if (w == 0.0) {
			return (1 / (Math.sqrt(2)));
		}
		return 1;

	}

}
